/****************************************************
	文件：SceneManager.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2021/1/17 17:51:49
	功能：场景 管理器
*****************************************************/

using System;
using System.Collections;
using HTFW.Core;
using HTFW.UI;
using HTFW.Utility.Global;
using UnityEngine;
using UnityEngine.SceneManagement;
using EventType = HTFW.Core.EventType;

namespace HTFW.Scene
{
    public delegate void SceneLoadHandle();

    public class SceneManager : Singleton<SceneManager>, IManager
    {
        /// <summary>
        /// 当前场景名
        /// </summary>
        public SceneType CurrentScene { get; private set; }

        /// <summary>
        /// 场景加载完成的标志位
        /// </summary>
        public bool IsAlreadyLoaded { get; private set; }

        int mLoadProgress;

        /// <summary>
        /// 加载场景进度（max num：100）
        /// </summary>
        public int LoadProgress
        {
            get { return mLoadProgress; }
            set
            {
                int newValue = Mathf.Clamp(value, 0, 100);
                if (newValue != mLoadProgress)
                {
                    mLoadProgress = newValue;
                    HTDriver.GlobalContext.EventContext.Publish(EventType.UpdateSceneLoadProgress, mLoadProgress);
                }
            }
        }

        SceneLoadHandle mOnCacheClear; //切换场景前的资源清理过程
        SceneLoadHandle mOnResPreload; //切换场景中的资源预加载过程
        SceneLoadHandle mOnLoaded; //切换场景完成回调

        public void Init(params object[] args)
        {
            IsAlreadyLoaded = true;
        }

        public void Dispose()
        {
            if (mLoadSceneCoro != null)
            {
                mLoadSceneCoro.Stop();
                mLoadSceneCoro = null;
            }
        }

        IRoutineHandle mLoadSceneCoro;

        /// <summary>
        /// 加载场景
        /// </summary>
        /// <param name="sceneType">场景类型（与场景名称一致）</param>
        /// <param name="onCacheClear">切换场景前的资源清理过程</param>
        /// <param name="onResPreload">切换场景中的资源预加载过程</param>
        /// <param name="onLoaded">切换场景完成回调</param>
        public void LoadScene(SceneType sceneType, SceneLoadHandle onCacheClear, SceneLoadHandle onResPreload,
            SceneLoadHandle onLoaded)
        {
            mOnCacheClear = onCacheClear;
            mOnResPreload = onResPreload;
            mOnLoaded = onLoaded;

            LoadProgress = 0;
            UIManager.Instance.CloseAllWindow(typeof(LoadingView));
            mLoadSceneCoro = CoroutineService.Instance.Start(AsyncLoadScene(sceneType), true);
        }

        static readonly YieldInstruction mWait = new WaitForEndOfFrame();

        private IEnumerator AsyncLoadScene(SceneType sceneType)
        {
            IsAlreadyLoaded = false;

            //-------------------- 步骤1：资源清理 --------------------//
            ClearCache(); //清空缓存资源
            mOnCacheClear?.Invoke();

            //-------------------- 步骤2：场景跳转 --------------------//
            int targetProgress = 0;
            AsyncOperation newScene =
                UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(sceneType.ToString(),
                    LoadSceneMode.Single); //跳转到新场景
            if (newScene != null && newScene.isDone == false)
            {
                newScene.allowSceneActivation = false; //加载的时候不显示新场景
                if (newScene.progress <= 0.30f) //先加载30%
                {
                    targetProgress = (int) (newScene.progress * 100);
                    while (LoadProgress <= targetProgress)
                    {
                        LoadProgress++;
                        yield return mWait;
                    }
                }

                //-------------------- 步骤3：资源预加载 --------------------//
                mOnResPreload?.Invoke();

                //再加载剩余70%（这一部分Unity执行非常快，所以自行模拟平滑加载）
                targetProgress = 100;
                while (LoadProgress <= targetProgress - 2)
                {
                    LoadProgress++;
                    yield return mWait;
                }

                //-------------------- 步骤4：场景加载完成 --------------------//
                LoadProgress = targetProgress;
                newScene.allowSceneActivation = true; //加载完成显示新场景

                CurrentScene = sceneType;
                IsAlreadyLoaded = true;

                mOnLoaded?.Invoke();
            }
        }

        /// <summary>
        /// 清除缓存资源
        /// </summary>
        private void ClearCache()
        {
        }
    }
}